package org.tom.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import net.bytebuddy.asm.Advice;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.tom.basic.exception.MyException;
import org.tom.order.domain.OrderPet;
import org.tom.order.domain.OrderPetDetail;
import org.tom.order.mapper.OrderPetDetailMapper;
import org.tom.order.mapper.OrderPetMapper;
import org.tom.pay.domain.PayAlipayInfo;
import org.tom.pay.domain.PayBill;
import org.tom.pay.domain.PayFlow;
import org.tom.pay.dto.AlipayNotifyDto;
import org.tom.pay.mapper.PayAlipayInfoMapper;
import org.tom.pay.mapper.PayBillMapper;
import org.tom.pay.mapper.PayFlowMapper;
import org.tom.pay.service.IPayService;
import org.tom.pet.domain.Pet;
import org.tom.pet.mapper.PetMapper;
import springfox.documentation.spring.web.json.Json;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class PayServiceImpl implements IPayService {
    @Autowired
    private PayBillMapper payBillMapper;

    @Autowired
    private PayAlipayInfoMapper payAlipayInfoMapper;

    @Autowired
    private PayFlowMapper payFlowMapper;

    @Autowired
    private OrderPetMapper orderPetMapper;

    @Autowired
    private OrderPetDetailMapper orderPetDetailMapper;

    @Autowired
    private PetMapper petMapper;

    @Override
    public String toPay(String sn) {
        if(sn == null){
            throw new MyException("订单号为空");
        }
        PayBill payBill = payBillMapper.loadBySn(sn);
        if (payBill == null){
            throw new MyException("该地址无效");
        }

        PayAlipayInfo payAlipayInfo = payAlipayInfoMapper.loadFrist();
        if (payAlipayInfo == null){
            throw new MyException("阿里配置无效");
        }
        // 1. 设置参数（全局只需设置一次）
        Factory.setOptions(payAlipayInfo.getOptions());
        try {
            String returnUrl = String.format(payAlipayInfo.getReturnUrl(), sn);
            // 2. 发起API调用（以创建当面付收款二维码为例）
            // payBill.getDigest() 摘要, payBill.getUnionPaySn() 订单号,payBill.getMoney().toString()金额,returnUrl 同步回调域,四个参数传到支付宝
            AlipayTradePagePayResponse response = Factory.Payment.Page()
                    .pay(payBill.getDigest(), payBill.getUnionPaySn(),payBill.getMoney().toString(),returnUrl);
            // 3. 处理响应或异常
            if (ResponseChecker.success(response)) {
                System.out.println("调用成功");
                // 返回前端的值，是html页面，拉起来就是 支付宝支付的页面
                return response.body;
            } else {
                System.err.println("调用失败，原因：");
            }
        } catch (Exception e) {
            System.err.println("调用遭遇异常，原因：" + e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }
        return "申请失败";
    }

    // 支付宝异步回调
    @Override
    public String alipayNotify(AlipayNotifyDto alipayNotifyDto) {
        // 先将对象妆化为json格式的字符串
        String s = JSON.toJSONString(alipayNotifyDto);
        // 将字符串转化为map
        Map<String,String> parameters = JSON.parseObject(s, Map.class);

        // 订单号
        String out_trade_no = alipayNotifyDto.getOut_trade_no();
        if (out_trade_no == null){
            System.out.println("单号为空");
            return "fail";
        }

        PayBill payBill = payBillMapper.loadBySn(out_trade_no);
        if (payBill == null){
            System.out.println("通过单号无法查到payBill");
            return "fail";
        }

        PayAlipayInfo alipayInfo = payAlipayInfoMapper.loadFrist();
        // 验签的操作这个是在开发文档中看到的，需要的参数为Map
        try {
            Boolean verifySignSuccess = Factory.Payment.Common().verifyNotify(parameters);
            if(!verifySignSuccess){
                System.out.println("验证签名失败...");
                return "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 幂等处理，防止多次操作数据库
        if (payBill.getState() != PayBill.WAIT_PAY){
            System.out.println("支付宝第二次调用");
            return "success";
        }

        // 比对金额
        
        String total_amount = alipayNotifyDto.getTotal_amount();
        BigDecimal bigDecimal = new BigDecimal(total_amount);
        BigDecimal money = payBill.getMoney();
        // compareTo表示比较0为相等
        if (money.compareTo(bigDecimal) != 0){
            System.out.println("金额不相等");
            return "fail";
        }

        PayAlipayInfo payAlipayInfo = payAlipayInfoMapper.loadFrist();
        String appid = payAlipayInfo.getAppid();
        String app_id = alipayNotifyDto.getApp_id();
        if (app_id == null){
            System.out.println("appid为空");
            return "fail";
        }
        if (!app_id.equals(appid)){
            System.out.println("appid不相同");
            return "fail";
        }

        // 保存支付流水
        PayFlow payFlow = new PayFlow();
        BeanUtils.copyProperties(alipayNotifyDto, payFlow);
        payFlowMapper.add(payFlow);

        // 修改支付状态
        if (alipayNotifyDto.isTradeExpire()){
            System.out.println("支付中");
            return "fail";
        }
        // 通过订单号查询订单
        OrderPet orderPet = orderPetMapper.loadBySn(out_trade_no);
        if (orderPet == null){
            System.out.println("通过订单号查不到订单");
            return "fail";
        }

        // 通过订单号查询订单的明细
        List<OrderPetDetail> orderPetDetail = orderPetDetailMapper.loadBySn(out_trade_no);
        // 查询查到宠物id的集合
        List<Long> petIds = orderPetDetail.stream().map(detail -> detail.getPetId()).collect(Collectors.toList());

        List<Pet> pets = petMapper.batchSelectByIds(petIds, Pet.STATE_ONLINE);


        if (alipayNotifyDto.isTradeSuccess()){ // 交易成功
            System.out.println("交易成功");
            payBill.setState(PayBill.PAY_SUCCESS);
            // 付款成功待发货
            orderPet.setState(OrderPet.SUCCESS_PAY_ORDER);
        } else if (alipayNotifyDto.isTradeExpire()){ // 交易未付款交易超时关闭，或支付完成后全额退款。
            System.out.println("未付款交易超时关闭，或支付完成后全额退款。");
            payBill.setState(PayBill.SATET_OUTTIME_OR_RETURN);
            orderPet.setState(OrderPet.CANCEL_PAY_ORDER);
            pets.forEach(pet -> {
                pet.setStore_number(pet.getStore_number()+1);
                petMapper.update(pet);
            });
        }else {
            System.out.println("其他状态");
            return "fail";
        }
        // 订单的最后修改的时间
        payBill.setLastPayTime(new Date());
        orderPetMapper.update(orderPet);
        payBillMapper.update(payBill);

        return "success";
    }


}
